package com.test.service;

import com.google.common.collect.Lists;
import com.test.entity.User;
import com.test.entity.UserContact;
import com.test.repository.UserContactMapper;
import com.test.repository.UserContactRepository;
import com.test.repository.UserMapper;
import com.test.repository.UserRepository;
import com.test.representation.UserContactRepresentation;
import com.test.representation.UserRepresentation;
import io.shardingsphere.core.keygen.KeyGenerator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by Jack on 6/30/2018.
 */
@Slf4j
@RequiredArgsConstructor
@Transactional
@Service
public class UserService {

  private final AtomicLong COUNTER = new AtomicLong(1000);

  private final UserRepository userRepository;
  private final UserMapper userMapper;

  private final UserContactRepository userContactRepository;
  private final UserContactMapper userContactMapper;

  private final KeyGenerator keyGenerator;

  public UserRepresentation getUserByUserId(Long userId) {
    deleteAll();
    List<User> users = Lists.newArrayList();
    for (int i = 0; i < 10; i++) {
      users.add(generateUser());
    }
    userRepository.insert(users.toArray(new User[users.size()]));
    log.info("user:{}", userMapper.selectByPrimaryKey(users.get(0).getId()));
    User user = userRepository.findByUserId(users.get(0).getUserId());
    return toUserRepresentation(user);
  }

  public List<UserRepresentation> getUserByName(String name) {
    deleteAll();
    List<User> users = Lists.newArrayList();
    for (int i = 0; i < 10; i++) {
      users.add(generateUser());
    }
    userRepository.insert(users.toArray(new User[users.size()]));
    return userRepository.findByName("Tom-1").stream().map(this::toUserRepresentation)
        .collect(Collectors.toList());
  }

  public List<UserContactRepresentation> getContactsByUserId(Long userId) {
    deleteAll();
    List<User> users = Lists.newArrayList();
    List<UserContact> contacts = Lists.newArrayList();
    for (int i = 0; i < 10; i++) {
      User user = generateUser();
      users.add(user);
      if (i % 2 == 0) {
        for (int j = 0; j < 3; j++) {
          UserContact contact = new UserContact();
          contact.setId(keyGenerator.generateKey().longValue());
          contact.setUserId(user.getUserId());
          contact.setName("Jerry-" + RandomUtils.nextInt(999, 9999));
          contact.setMobile("131" + RandomUtils.nextInt(10000000, 99999999));
          contacts.add(contact);
        }
      }
    }
    userContactRepository.insert(contacts.toArray(new UserContact[contacts.size()]));
    userRepository.insert(users.toArray(new User[users.size()]));
    return userContactRepository.findByUserId(contacts.get(0).getUserId()).stream()
        .map(this::toUserContactRepresentation).collect(Collectors.toList());
  }

  public List<UserRepresentation> findByPagination(Integer pageSize) {
    deleteAll();
    List<User> users = Lists.newArrayList();
    for (int i = 0; i < 10; i++) {
      User user = generateUser();
      users.add(user);
    }
    userRepository.insert(users.toArray(new User[users.size()]));
    return userRepository.findByPagination(5).stream().map(this::toUserRepresentation)
        .collect(Collectors.toList());
  }

  private void deleteAll() {
    userContactRepository.deleteAll();
    userRepository.deleteAll();
  }

  private User generateUser() {
    User user = new User();
    user.setId(keyGenerator.generateKey().longValue());
    user.setUserId(COUNTER.incrementAndGet());
    user.setName("Tom-" + RandomUtils.nextInt(100, 999));
    user.setMobile("138" + RandomUtils.nextInt(10000000, 99999999));
    return user;
  }

  private UserRepresentation toUserRepresentation(User user) {
    UserRepresentation representation = new UserRepresentation();
    BeanUtils.copyProperties(user, representation);
    return representation;
  }

  private UserContactRepresentation toUserContactRepresentation(UserContact contact) {
    UserContactRepresentation representation = new UserContactRepresentation();
    BeanUtils.copyProperties(contact, representation);
    return representation;
  }
}
